/*
 * thread.cpp
 *
 *  Created on: 2008-8-13
 *      Author: fanliangliang
 */

#include "bits/thread.h"
#include "bits/tss.h"
#include <windows.h>
#include <process.h>

BEGIN_NAMESPACE_TOXIC

__stdcall unsigned Thread::start_routine(void* arg) {
	Thread* thread = static_cast<Thread*>(arg);
	if (thread->_target != 0) {
		thread->_target->run();
	}
	else {
		thread->run();
	}
	toxic::detail::tss::cleanup();
	return 0;
}

Thread::Thread()
:_target(0)
,_tid(0)
,_handle(0) {

}

Thread::~Thread() {
	if (_handle != 0) {
		CloseHandle(_handle);
	}
	delete _target;
}

void Thread::run() {

}

void Thread::start() {
	if (_handle == 0) {
		_handle = reinterpret_cast<void*>(_beginthreadex(0, 0, start_routine, this, CREATE_SUSPENDED, &_tid));

		if (_handle == 0) {
			throw ThreadException("'_beginthreadex()' failed");
		}

		if (ResumeThread(_handle) == size_t(-1)) {
			throw ThreadException("'ResumeThread()' failed");
		}
	}
}

void Thread::join() {
	if (_handle != 0) {
		WaitForSingleObject(_handle, INFINITE);
		CloseHandle(_handle);
		_handle = 0;
	}
}

size_t Thread::id() const {
	return _tid;
}

void Thread::yield() {
	Sleep(0);
}

void Thread::sleep(unsigned long ms) {
	Sleep(ms);
}

size_t Thread::self() {
	return GetCurrentThreadId();
}

bool operator==(const Thread& lhs, const Thread& rhs) {
	return lhs.id() == rhs.id();
}

bool operator!=(const Thread& lhs, const Thread& rhs) {
	return lhs.id() != rhs.id();
}

END_NAMESPACE_TOXIC
